package com.flame.shapeville.component.bonus2;

import javafx.concurrent.Worker;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.web.WebView;
import lombok.Getter;

/**
 * Represents a sector of a circle used in Bonus Task 2.
 * <p>
 * This class is responsible for rendering a circular sector with customizable angle,
 * radius, and unit. It also supports detailed explanation view with formula rendering.
 *
 * @author Flame Dev Team
 * @version 1.0
 * @since 2025-05-18
 */
public class Sector {

    /**
     * The main pane containing the visual representation of the sector.
     */
    @Getter
    private Pane shape;

    /**
     * A detailed pane that includes additional explanations and formulas.
     */
    @Getter
    AnchorPane detailedShape = new AnchorPane();

    /**
     * The size of the drawing area (determines layout scale).
     */
    private double size;

    /**
     * X-coordinate center of the circle.
     */
    private double x;

    /**
     * Y-coordinate center of the circle.
     */
    private double y;

    /**
     * Radius of the circle based on the drawing size.
     */
    private double r;

    /**
     * Starting angle of the sector (in degrees).
     */
    private double startAngle;

    /**
     * Sweep angle of the sector (in degrees).
     */
    private double angle;

    /**
     * Actual radius value used for calculations.
     */
    private double radius;

    /**
     * Unit of measurement displayed in labels (e.g., "cm", "m").
     */
    private String unit;

    /**
     * Constructs a new Sector with default size and given parameters.
     *
     * @param startAngle starting angle of the sector (in degrees)
     * @param angle      sweep angle of the sector (in degrees)
     * @param radius     actual radius of the circle
     * @param unit       unit of measurement to display
     */
    public Sector(double startAngle, double angle, double radius, String unit) {
        this(200, startAngle, angle, radius, unit);
    }

    /**
     * Constructs a new Sector with specified size and basic parameters.
     *
     * @param size       the width/height of the drawing area
     * @param startAngle starting angle of the sector (in degrees)
     * @param angle      sweep angle of the sector (in degrees)
     */
    public Sector(double size, double startAngle, double angle) {
        this(size, startAngle, angle, 0, null);
    }

    /**
     * Full constructor for creating a sector with all custom parameters.
     *
     * @param size       the width/height of the drawing area
     * @param startAngle starting angle of the sector (in degrees)
     * @param angle      sweep angle of the sector (in degrees)
     * @param radius     actual radius of the circle
     * @param unit       unit of measurement to display
     */
    public Sector(double size, double startAngle, double angle, double radius, String unit) {
        this.size = size;
        this.startAngle = startAngle;
        this.angle = angle;
        this.radius = radius;
        this.unit = unit;
        if (size > 100) {
            shape = new AnchorPane();
            shape.setPrefSize(480, 240);
            x = 240;
            y = 100;
        } else {
            shape = new AnchorPane();
            x = y = size / 2;
        }
        r = size / 2;
        loadShape(shape);
        initDetailed();
    }

    /**
     * Loads the visual representation of the sector into the provided pane.
     *
     * @param shape the pane where the sector will be drawn
     */
    public void loadShape(Pane shape) {
        int weight = size > 150 ? 4 : 2;

        Circle circle = new Circle(x, y, r);
        circle.setFill(null);
        circle.setStroke(Color.BLACK);
        circle.setStrokeWidth(weight);

        Circle centPoint = new Circle(x, y, weight, Color.BLACK);

        Arc arc = new Arc(x, y, r, r, startAngle, angle);
        arc.setFill(Color.web("#FABBAA"));
        arc.setStroke(Color.BLACK);
        arc.setType(ArcType.ROUND);
        arc.setStrokeWidth(weight);

        shape.getChildren().addAll(circle, arc, centPoint);

        if (size < 150) return;

        if (Math.abs(angle - 90) < 0.1) {
            drawRightAngleLines(shape);
        } else {
            Arc indicator = new Arc(x, y, 20, 20, startAngle, angle);
            indicator.setType(ArcType.OPEN);
            indicator.setStroke(Color.BLACK);
            indicator.setFill(null);
            shape.getChildren().add(indicator);
        }

        Label label = new Label(String.format("%.0f°", angle));
        double mid = startAngle + angle / 2;
        double rad = Math.toRadians(-mid);
        double dx = 40 * Math.cos(rad), dy = 40 * Math.sin(rad);
        label.setLayoutX(x + dx);
        label.setLayoutY(y + dy);
        shape.getChildren().add(label);
    }

    /**
     * Draws right-angle indicators when the sector's angle is exactly 90 degrees.
     *
     * @param shape the pane where the lines will be drawn
     */
    private void drawRightAngleLines(Pane shape) {
        double a1 = Math.toRadians(-startAngle);
        double a2 = Math.toRadians(-(startAngle + 90));

        double offset = 15, len = 15;

        double xA = x + offset * Math.cos(a1);
        double yA = y + offset * Math.sin(a1);
        double xB = x + offset * Math.cos(a2);
        double yB = y + offset * Math.sin(a2);

        double xC = xA + len * Math.cos(a2);
        double yC = yA + len * Math.sin(a2);
        double xD = xB + len * Math.cos(a1);
        double yD = yB + len * Math.sin(a1);

        Line line1 = new Line(xA, yA, xC, yC);
        Line line2 = new Line(xB, yB, xD, yD);
        line1.setStroke(Color.BLACK);
        line2.setStroke(Color.BLACK);
        shape.getChildren().addAll(line1, line2);
    }

    /**
     * Initializes the detailed view of the sector.
     * Includes formula explanation using an embedded web view.
     */
    private void initDetailed() {
        if (size < 100) return;
        x = 120;
        y = 120;
        detailedShape = new AnchorPane();
        detailedShape.setPrefSize(480, 240);

        Label label = new Label("radius = " + radius + " " + unit);
        detailedShape.getChildren().add(label);

        loadShape(detailedShape);

        Line dashedLine = new Line();
        dashedLine.setStartX(239);
        dashedLine.setStartY(20);
        dashedLine.setEndX(239);
        dashedLine.setEndY(220);
        dashedLine.setStroke(Color.GRAY);
        dashedLine.setStrokeWidth(2);
        dashedLine.getStrokeDashArray().addAll(10d, 4d);
        dashedLine.setTranslateX(x - 1);

        double answer = 3.14 * radius * radius * angle / 360;

        WebView webView = new WebView();
        webView.setPrefSize(220, 240);
        webView.setLayoutX(241);
        webView.setStyle("-fx-background-color: transparent;");
        String url = getClass().getResource("/static/formula/bonus2/sector.html").toExternalForm();
        webView.getEngine().load(url);
        webView.getEngine().getLoadWorker().stateProperty().addListener((obs, oldState, newState) -> {
            if (newState == Worker.State.SUCCEEDED) {
                webView.getEngine().executeScript("updateFormula(" + angle + "," + radius + "," + answer + ", \"" + unit + "\")");
            }
        });

        detailedShape.getChildren().addAll(dashedLine, webView);
    }
}
